package com.flex.showdoc4j.spring;

import com.flex.showdoc4j.config.Configuration;
import com.flex.showdoc4j.executor.SimpleDocResolver;
import com.flex.showdoc4j.executor.Wrapper;
import com.flex.showdoc4j.executor.interfaces.DocResolver;
import com.flex.showdoc4j.executor.interfaces.Render;
import com.flex.showdoc4j.filter.MvcFilter;
import com.flex.showdoc4j.model.ConfigModel;
import org.springframework.context.ApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * spring 文档创建工厂
 *
 * @author ganlt<br>
 * @since 2019/06/26 14:46 <br>
 */
public class SimpleSpringDocFactory implements SpringDocFactory {
    private Configuration configuration;
    @SuppressWarnings("unused")
	private DocResolver docResolver;

    public SimpleSpringDocFactory() {
        this.configuration = new Configuration();
        this.docResolver = new SimpleDocResolver(configuration);
    }

    @Override
    public void createDoc(SpringRequestMappingHandler handler, ConfigModel configModel, MvcFilter includeMvcFilter) {
        AbstractHandlerMapping handlerMapping = handler.getHandlerMapping();
        configurationInit(configModel);
        if (handlerMapping instanceof RequestMappingInfoHandlerMapping) {
            RequestMappingInfoHandlerMapping requestMappingHandler = (RequestMappingInfoHandlerMapping) handlerMapping;
            ApplicationContext applicationContext = requestMappingHandler.getApplicationContext();
            Map<RequestMappingInfo, HandlerMethod> handlerMaps = requestMappingHandler.getHandlerMethods();
            List<Wrapper> wrappers = new ArrayList<>();
            configuration.setWrappers(wrappers);
            configuration.setApplicationContext(applicationContext);
            for (Map.Entry<RequestMappingInfo,HandlerMethod> entry : handlerMaps.entrySet()) {
                RequestMappingInfo info = entry.getKey();
                HandlerMethod method = entry.getValue();
                Iterator<String> infoIterator = info.getPatternsCondition().getPatterns().iterator();
                if (infoIterator.hasNext()) {
                    String patterUrl = infoIterator.next();
                    boolean isInclude = includeMvcFilter.match(patterUrl);
                    if (!isInclude) {
                        continue;
                    }
                    register(patterUrl, method.getMethod(), method);
                    DocResolver docResolver = configuration.getDocResolver();
                    Wrapper wrapper = docResolver.lookMethod(patterUrl, method.getMethod());
                    if (wrapper != null) {
                        wrapper.setConfiguration(configuration);
                        wrapper.setPatternUrl(patterUrl);
                        wrappers.add(wrapper);
                    }
                }
            }

            Render render = configuration.getRender();
            render.render(configuration);
        }


    }

    private void configurationInit(ConfigModel configModel) {
        this.configuration.setConfigModel(configModel);
    }

    @Override
    public void createDoc(String packages, ConfigModel configModel) {

    }

    private void register(String info, Object control, Object controlBean) {
        configuration.addControl(info, control);
        configuration.addControlBean(info, controlBean);
    }

}
